import { ButtonDevOnly } from "@/component/ButtonDevOnly";
import { Notificatorio } from "@/hooks/Providers";
import { contacts_forage, ghost_messages_forage, IEnsuredTask, ITaskInfo as ITaskInfo_, sessions_forage } from "@/mgr";
import { tasks_keeper } from "@/mgr/tasks/instance";
import { show_raw_jsons } from "@/utils/show_raw_jsons";
import { ReloadOutlined } from "@ant-design/icons";
import { Button, Checkbox, Flex, InputNumber, Select, Typography } from "antd";
import { DefaultOptionType } from "antd/es/select";
import { useEffect, useRef, useState } from "react";
import { FlexHeader, FlexRoot, ListEmpty } from "../_BaseView/FlexRoot";
import { List } from "../_BaseView/List";
import { TaskItem } from "./TaskItem";
const { Text } = Typography;
type ITaskInfo = Required<ITaskInfo_<any, any>>

const input_style = { width: 65 };
export default function TasksView() {
  const ref_max_size = useRef(10)
  const [interval, set_interval] = useState(1000);
  const ref_task = useRef<[ITaskInfo, string][]>([]);
  const [pendings, set_pendings] = useState(0);
  const [waitings, set_waitings] = useState(0);
  const [tasks, set_tasks] = useState<ITaskInfo[]>([])
  const [auto_update, set_auto_update] = useState(true);
  const [auto_submit, set_auto_submit] = useState(tasks_keeper().auto_submit)
  const [auto_collect, set_auto_collect] = useState(tasks_keeper().auto_collect)
  const ref_prev_task_types = useRef<string>('')
  const ref_task_types = useRef<string[]>([])
  const [task_type_options, set_task_type_options] = useState<DefaultOptionType[]>()

  const update_list = () => {
    set_pendings(tasks_keeper().penddings.length)
    set_waitings(tasks_keeper().waitings.length);
    const { penddings, waitings } = tasks_keeper();
    const l1 = penddings.length;
    const l2 = waitings.length;
    const task_types = ref_task_types.current;
    const max_size = ref_max_size.current;
    const l = Math.min(l1 + l2, max_size)

    const task_types_str = task_types.join();
    if (task_types_str !== ref_prev_task_types.current) {
      ref_prev_task_types.current = task_types_str
    } else if (ref_task.current.length >= max_size) {
      let list_changed = ref_task.current.length > max_size;
      let list_all_done = true;
      for (const pair of ref_task.current) {
        const [task, prev_status] = pair;
        if (task.status !== prev_status) {
          pair[1] = task.status;
          list_changed = true;
        }
        if (prev_status !== 'rejected' && prev_status !== 'resolved') {
          list_all_done = false
        }
      }
      ref_task.current.length = max_size;
      if (list_changed) set_tasks(v => {
        return v.length > max_size ? v.splice(0, max_size) : [...v];
      })
      if (!list_all_done || list_changed) return;
    }
    ref_task.current.length = 0
    const tasks: IEnsuredTask<any, any>[] = []

    for (let i = 0; i < l1 + l2 && tasks.length < l; i++) {
      const task = i < l1 ? penddings[i] : waitings[i + l1]
      if (task_types.length && !task_types.some(t => t == task.type))
        continue;
      tasks.push(task)
      ref_task.current.push([task, task.status]);
    }
    set_tasks(tasks);
  }

  useEffect(() => {
    if (!auto_update) return;
    console.log("auto_update: " + auto_update)
    const tid = setInterval(() => update_list(), interval)
    return () => clearInterval(tid);
  }, [auto_update, interval])

  useEffect(() => {
    const update = () => {
      set_task_type_options(tasks_keeper().task_types.map(value => ({ value })))
    }
    update();
    return tasks_keeper().callbacks.add({
      on_type_add: update
    })
  }, [])

  const render_item = (v: ITaskInfo) => {
    return (
      <TaskItem
        task={v}
        key={v.id}
        on_click_close={() => {
          tasks_keeper().del(v.id)
          ref_task.current = ref_task.current.filter(o => o[0].id !== v.id)
          set_tasks(old => old.filter(o => o.id !== v.id))
        }}
        on_click_submit={() => {
          tasks_keeper().start(v.id)
        }}
      />
    )
  }
  const [n] = Notificatorio.use()
  return (
    <FlexRoot vertical>
      <FlexHeader wrap justify='flex-start'>
        <Flex flex={1} wrap align='center' gap={5}>
          <Text type='secondary' title="观察的任务类型">
            观察类型{' '}
            <Select
              placeholder='全部'
              style={{ minWidth: 120 }}
              onChange={v => ref_task_types.current = v?.sort()}
              options={task_type_options}
              size='small'
              maxTagCount={2}
              showSearch={false}
              suffixIcon={null}
              variant='underlined'
              mode='multiple' />
          </Text>
          <Text type='secondary' title="观察队列前指定数量的任务">
            观察数{' '}
            <InputNumber
              size='small'
              variant='underlined'
              min={1}
              max={3000}
              style={input_style}
              defaultValue={ref_max_size.current}
              step={1}
              onChange={v => ref_max_size.current = v || 1} />
          </Text>
          <Text type='secondary' title='刷新间隔时间'>
            间隔{' '}
            <InputNumber
              size='small'
              variant='underlined'
              min={1}
              style={input_style}
              value={interval}
              step={1}
              onChange={v => set_interval(v || 1)} />
            毫秒
          </Text>
          <Text type='secondary' title='任务执行数, 最多同时执行的任务数'>
            执行数{' '}
            <InputNumber
              size='small'
              variant='underlined'
              min={1}
              style={input_style}
              defaultValue={tasks_keeper().max_executions}
              step={1}
              max={100}
              onChange={v => { tasks_keeper().max_executions = v ?? 1 }} />
          </Text>
          <Text type='secondary' style={{ cursor: 'pointer' }}>
            <Text type='secondary' onClick={() => set_auto_update(!auto_update)}>
              自动刷新
            </Text>{' '}
            <Checkbox title='自动刷新' checked={auto_update} onChange={e => set_auto_update(e.target.checked)} />
          </Text>
          <Text type='secondary' style={{ cursor: 'pointer' }}>
            <Text type='secondary' onClick={() => { set_auto_submit(tasks_keeper().auto_submit = !auto_submit); }}>
              自动提交
            </Text>{' '}
            <Checkbox title='自动提交' checked={auto_submit} onChange={e => set_auto_submit(tasks_keeper().auto_submit = e.target.checked)} />
          </Text>
          <Text type='secondary' style={{ cursor: 'pointer' }}>
            <Text type='secondary' onClick={() => { set_auto_collect(tasks_keeper().auto_collect = !auto_collect); }}>
              自动采集
            </Text>{' '}
            <Checkbox title='自动提交' checked={auto_collect} onChange={e => set_auto_collect(tasks_keeper().auto_collect = e.target.checked)} />
          </Text>
          {
            auto_update ? null :
              <Button size="small" type='text' onClick={() => update_list()}>
                <ReloadOutlined />
              </Button>
          }
        </Flex>
        <Text type='secondary' title="进行中任务数|等待任务数">
          任务数{' '}
          <Text strong >{pendings} | {waitings}</Text>
        </Text>
        <ButtonDevOnly onClick={async () => {
          show_raw_jsons([
            "说明：任务提交成功后，将会记录一些信息在本地，用于提供“管理类”进行“是否是要提交任务”判断。\n" +
            "针对“会话”或“联系人”，将会用本地记录进行差异比较, 只有有变化才会进行提交.\n" +
            "针对“消息”，一旦存在则不会提交（因为消息基本不可变，且数量极大）。" +
            "若清空这些本地记录，可能会触发重新进行提交",
            ['联系人记录', await contacts_forage.keys()],
            ['会话记录', await sessions_forage.keys()],
            ['消息记录', await ghost_messages_forage.keys()],
          ], {
            title: '本地记录', icon: null, footer: <Flex gap={5} justify='flex-end' style={{ display: 'flex', padding: 10 }}>
              <Button
                danger size='small' type='primary'
                onClick={() => sessions_forage.clear().then(() => n.info({ message: '清空会话提交记录 done' }))}>
                清空会话提交记录
              </Button>
              <Button
                danger size='small' type='primary'
                onClick={() => contacts_forage.clear().then(() => n.info({ message: '清空联系人提交记录 done' }))}>
                清空联系人提交记录
              </Button>
              <Button
                danger size='small' type='primary'
                onClick={() => ghost_messages_forage.clear().then(() => n.info({ message: '清空消息提交记录 done' }))}>
                清空消息提交记录
              </Button>
            </Flex>
          })
        }}>
          本地记录
        </ButtonDevOnly>
        <ButtonDevOnly onClick={async () => {
          tasks_keeper().waitings.length = 0;
          set_tasks([])
          set_pendings(0);
          set_waitings(0);  
        }}>
          删除全部
        </ButtonDevOnly>
      </FlexHeader>
      <List
        data={tasks}
        virtual={tasks.length > 100}
        itemHeight={120}
        itemKey="id"
        others={<ListEmpty show={!tasks.length} />}>
        {render_item}
      </List>
    </FlexRoot >
  )
}
